package com.freewater.cargotracker.domain.model.location;

import org.apache.commons.lang3.Validate;

import java.io.Serializable;
import java.util.Objects;

/**
 * A location in our model is stops on a journey, such as cargo origin or
 * destination, or carrier movement end points.
 * <p>
 * It is uniquely identified by a UN location code.
 */
public class Location implements Serializable {

    private static final long serialVersionUID = 1L;

    public static final Location UNKNOWN = new Location(new UnLocode("xxxxx"), "Unknown location");

    private Long id;
    private UnLocode unLocode;
    private String name;

    /**
     * @param unLocode UN Locode
     * @param name     Location name
     * @throws IllegalArgumentException if the UN Locode or name is null
     */
    public Location(UnLocode unLocode, String name) {
        Validate.notNull(unLocode, "UnLocode is required");
        Validate.notNull(name, "Name is required");

        this.unLocode = unLocode;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        Validate.notNull(id, "id is required");
        this.id = id;
    }

    /**
     * @return UN Locode for this location.
     */
    public UnLocode getUnLocode() {
        return unLocode;
    }

    /**
     * @return Actual name of this location, e.g. "Stockholm".
     */
    public String getName() {
        return name;
    }

    /**
     * @param other to compare
     * @return Since this is an entity this will be true if UN locodes are
     * equal.
     */
    public boolean sameValueAs(Location other) {
        return other != null && this.unLocode.sameValueAs(other.unLocode);
    }

    /**
     * @param obj to compare
     * @return Since this is an entity this will be true if UN locodes are
     * equal.
     * @see #sameValueAs(Location)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || !(obj instanceof Location)) {
            return false;
        }
        final Location other = (Location) obj;
        return this.sameValueAs(other);
    }

    /**
     * @return Hash code of UN locode.
     */
    @Override
    public int hashCode() {
        return Objects.hash(unLocode);
    }

    @Override
    public String toString() {
        return "Location{" +
                "id=" + id +
                ", unLocode=" + unLocode +
                '}';
    }
}
